#include "connpool.h"


/*
 *@brief:
 */
int initConnPool(struct workerPthread_ctx **ctx, size_t maxConnSize){
	int iRet = RET_ERROR;
	struct workerPthread_ctx *tmp = *ctx;
	struct webServerCtx *server = (struct webServerCtx *)(tmp->ctx);
	bool keepAlive = server->opt->keepAlive;
	if(!tmp || maxConnSize < 0){
		fprintf(stderr,"[error]get unavaliable args in file:[%s] func:[%s] line:[%d]\n", __FILE__,__func__,__LINE__);
		return iRet;
	}
	tmp->connpoolsize = maxConnSize;
	tmp->connpool = (struct connection *)malloc(sizeof(struct connection) * tmp->connpoolsize);
	if(!(tmp->connpool)){
		fprintf(stderr,"[error]%s in file:[%s] func:[%s] line:[%d]\n", strerror(errno), __FILE__,__func__,__LINE__);
		return iRet;
	}
	memset(tmp->connpool, 0, sizeof(struct connection)*maxConnSize);
	if(keepAlive){

	}
	*ctx = tmp;
	return RET_OK;
}

/*
 *
 */
int addConnection(struct workerPthread_ctx *work, int fd){
#define BUF_SIZE 2048
	int iRet = RET_ERROR;
	if(!ctx || fd < 0){
		fprintf(stderr, "[error]get unavaliable args in file:[%s] func:[%s] line:[%d]\n", __FILE__,__func__,__LINE__);
		return iRet;
	}
    setfdNoBlock(fd);
	struct connection * conn = &(work->connpool[fd]);
	if(fd < work->connpoolsize){
		//必须确保空闲;
		INIT_CONNECTION(conn, fd, BUF_SIZE);
		iRet = work->workerIo->ModEvent(work->workerIo, fd, EPOLL_CTL_ADD, EPOLLIN|EPOLLET);
		work->currentConnNum++;
		//LogInfo(ctx, "%s%d%s%d%s\n","worker Thread:[", syscall(SYS_gettid),"] add a new connection:", fd ," successfully!");
		return RET_OK;
	}else{
		//重新申请
		return RET_OK;
	}
}

/*@brief:
 *@para:
 *
 */
int delConnection(struct workerPthread_ctx *work, int fd){
	int iRet = RET_ERROR;
	if(!ctx||fd < 0){
		fprintf(stderr, "[error]get unavaliable args in file:[%s] func:[%s] line:[%d]\n", __FILE__,__func__,__LINE__);
		return iRet;
	}
	if (fd >= work->connpoolsize){
		fprintf(stderr, "[error]get unavaliable fd:%d in file:[%s] func:[%s] line:[%d]\n", fd, __FILE__,__func__,__LINE__);
		return iRet;
	}
	//确保有效才可以删除;
	struct connection *conn  = &(work->connpool[fd]);
	conn->onclose = true;
	if(conn->onclose == true){
		/*
		 *改为宏函数更好
		 */
		iRet = work->workerIo->delEvent(work->workerIo, conn->connfd);
    	if(iRet == RET_ERROR){
        	fprintf(stderr, "[error]%s in file:[%s] func:[%s] line:[%d]\n",strerror(errno),__FILE__,__func__,__LINE__);
			return iRet;
    	}
		RESET_CONNECTION(conn);		
#ifdef __DEBUG_ON__
		DEBUG_TRACE(("[debug]worker Thread:%ld delete connection:%d\n", syscall(SYS_gettid), fd));
#endif 
		close(fd);
		work->currentConnNum--;
		DEBUG_TRACE(("[debug]worker Thread:[%ld] has connection num:%ld\n", syscall(SYS_gettid), work->currentConnNum));
		return RET_OK;
	}else{
		//无效;
		return RET_ERROR;
	}
}


void ConnPoolDeinit(struct workerPthread_ctx *work){
	if(!work){
		fprintf(stderr, "[error]get unavaliable args in file:[%s] func:[%s] line:[%d]\n", __FILE__,__func__,__LINE__);
		return;
	}
	int index = 0;
	LogInfo(ctx, "%s%d%s\n","worker Thread:[", syscall(SYS_gettid),"] deinit connpool.....!");
	if(work->connpoolsize > 0){
		for( ; index < work->connpoolsize; index++){
			struct connection *conn = &(work->connpool[index]);
			if(conn->sendbuf){
				free(conn->sendbuf);
				conn->sendbuf = NULL;
			}
			if(conn->recvbuf){
				free(conn->recvbuf);
				conn->recvbuf = NULL;
			}
		}
		if(work->connpool){
			free(work->connpool);
			work->connpool = NULL;
			work->connpoolsize = 0;
		}
	}
	return;
}

/*
 *@
 */
size_t readDataFromClient(int fd, unsigned char *buf, size_t len){
	int iRet = RET_ERROR;
	if(fd < 0 || !buf){
		fprintf(stderr, "[error]get unavaliable args in file:[%s] func:[%s] line:[%d]\n", __FILE__, __func__,__LINE__);
		return iRet;
	}
	size_t recvLen = 0;
	size_t dataLen = 0;
	for(;;){
		recvLen = recv(fd, buf+dataLen, len - dataLen, MSG_DONTWAIT);
		if(recvLen < 0){
			if(errno == EAGAIN||errno == EWOULDBLOCK||errno == EINTR){
				continue;
			}
			return RET_ERROR;
		}else if(recvLen == 0){	
			return RET_OK;
		}else{
			dataLen += recvLen;
			break;
		}
	}
	return  dataLen;
}

/*
 *@
 */
size_t writeDataToClient(int fd, unsigned char *buf, size_t len){
	int iRet = RET_ERROR;
	if(fd < 0 || !buf){
		fprintf(stderr, "[error]get unavaliable args in file:[%s] func:[%s] line:[%d]\n", __FILE__, __func__,__LINE__);
		return iRet;
	}
	int sent = 0;
	size_t dataLen = 0;
	for(;;){
		sent = send(fd, buf+dataLen, len - dataLen, MSG_DONTWAIT);
		if(sent < 0 ){
			if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR){
				continue;
			}
			return RET_ERROR;
		}else if(sent == 0){	
			return RET_OK;
		}else{
			dataLen += sent;
			break;
		}
	}
	return  dataLen;
}

